package modules.ulock;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


/**
 * 锁的理解
 *      1. 公平锁、非公平锁
 *      2. 可重入锁（递归锁）
 * @author shengren.yan
 * @create 2021-04-16
 */
@SpringBootTest
public class ULock1 {

    // 公平锁、非公平锁
    @Test
    void test1(){
        // 公平锁
        // NonfairSync lock = new FairSync();
        // 非公平锁
        // new NonfairSync()
    }

    // 可重入锁 （递归锁）
    @Test
    void test2(){
        // 拿到外面的锁，里面的锁也拿到了
        Phone phone = new Phone();

        new Thread(()->{ phone.seedMsg(); },"A").start();

        new Thread(()->{ phone.seedMsg(); },"B").start();

        // 结果：A线程，执行seedMsg和call方法后，B线程才拿到锁
    }

    // 可重入锁 （递归锁）
    @Test
    void test3(){
        // 拿到外面的锁，里面的锁也拿到了
        Phone2 phone = new Phone2();

        new Thread(()->{ phone.seedMsg(); },"A").start();

        new Thread(()->{ phone.seedMsg(); },"B").start();

        // 结果：A线程，执行seedMsg和call方法后，B线程才拿到锁
    }

}

class Phone{

    public synchronized void seedMsg(){
        System.out.println(Thread.currentThread().getName() + " ： 发短信");
        call();
    }

    public synchronized void call(){
        System.out.println(Thread.currentThread().getName() + " : 打电话");
    }

}

class Phone2{

    // lock锁必须配对
    Lock lock = new ReentrantLock();

    public void seedMsg(){
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " ： 发短信");
            call(); // 这里也有锁
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
          lock.unlock();
        }
    }

    public void call(){
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " : 打电话");
        } finally {
            lock.unlock();
        }
    }

}
